function data = data_getter(G)
  % Get data from Mooring_COTS_Dev, calculate or grab DO, and pass back to driver
  %
  % Author: David Goldsmith, Wash. State Dept. of Ecology, dgol461@ecy.wa.gov
  % Release date: < 9/15/2011

% TODO: Replace reportError and reportQueryError calls w/ equivalents in Utils\error_notification.m    
  % Open the database connection
    siteID = G.siteID;
    conn = database('Mooring_COTS_Dev', '', '');
  % Site data
    sitedata = queries(conn, 'site', {siteID});

  % Get the PostedUTCDatetime and ProcessedFlag values within t_interval
    PDTPFs = queries(conn, 'PDTPF', {siteID, G.t_interval});
    if ischar(PDTPFs{1})
        data = {sitedata, PDTPFs};
        return
    else
      % Unpack
        [nr,~] = size(PDTPFs);
        [PF{1:nr}, PDTs{1:nr}] = deal(PDTPFs{:});
        PF = cell2mat(PF);

        if G.doDO && any(~PF) % will need info from the following "static" tables
          % SiteEquipment Table
            equipdata = queries(conn, 'equipment', {siteID, G.t_interval(2)});
            [nr,~] = size(equipdata);
            [equipID{1:nr}, statID{1:nr}, equipNom{1:nr}, UTCDDT{1:nr}, AuxChanID{1:nr}, calibType{1:nr},...
                resColID{1:nr}, SiteID{1:nr}] = deal(equipdata{1:nr,:});
          % ResultColumn Table
            RCdata = queries(conn, 'RC', {});
            [nr,~] = size(RCdata);
            [RCID{1:nr}, RCN{1:nr}] = deal(RCdata{1:nr,:});
          % Calibration Table
            calibdata = queries(conn, 'calib', {equipID, calibType, UTCDDT});
            [nr,~] = size(calibdata);
            [equipID2{1:nr}, calibBegin{1:nr}, calibEnd{1:nr}, equipNom3{1:nr},...
                calibType2{1:nr}, calibForm{1:nr}, calibID{1:nr}] = ...
                deal(calibdata{1:nr, 1:7});
            c(1:nr,1:13) = calibdata(1:nr,8:20);
    % TODO: Add grabbing of other tables (not immediately needed to calculate DO)
    %             [nr, ~] = size(invendata);
    %             [equipNom2{1:nr}, serialNoDesc{1:nr}, equipTypeID{1:nr}, manufacturer{1:nr}, modelDesc{1:nr}] = ...
    %                     deal(invendata{1:nr,:});
    %             for j=1:nr
    %                 assert(ismember(equipNom1{i}, equipNom2), 'Error from EquipmentInventory table: EquipmentName mismatch!');
    %             end
    %             caltypdat = queries('caltyp', {calibType});
    %             if ischar(caltypdat)
    %                 data = reportQueryError(G.oEN.mail_recip, siteID, 'calibration type data', caltypdat, G.tag);
    %                 return
    %             end
    %             [nr, ~] = size(caltypdat);
    %             [calibType3{1:nr}, calibDesc{1:nr}] = deal(caltypdat{1:nr,:});
    %             for j=1:nr
    %                 assert(ismember(calibType{i}, calibType3), 'Error from CalibrationType table: CalibrationTypeID mismatch!');
    %             end
    % 
    %             calformdat = queries('calform', {calibForm});
    %             if ischar(calformdat)
    %                 data = reportQueryError(G.oEN.mail_recip, siteID, 'calibration formula data', calformdat, G.tag);
    %                 return
    %             else
    %                 [nr, ~] = size(calformdat);
    %                 [calibForm2{1:nr}, formNom{1:nr}, formDesc{1:nr}, storedProc{1:nr}, unitsDesc{1:nr}] = deal(calformdat{1:nr,:});
    %                 for j=1:nr
    %                     assert(ismember(calibForm2{i}, calibForm), 'Error from CalibrationFormula table: CalibrationFormulaID mismatch!');
    %                 end
    %             end
        end
      % Now get data all the data _except_ DO
        jointdata = queries(conn, 'joint', {siteID, G.t_interval});
        checkResult = check4QueryError(jointdata);
        if ~isempty(checkResult)
            data = reportQueryError(G.oEN.mail_recip, siteID, 'Joint data query', checkResult, G.tag);
            return
        end
        [nr,~] = size(jointdata);
        try
            [RVID{1:nr},SiteID{1:nr},PDT{1:nr},P{1:nr},T{1:nr},C{1:nr},S{1:nr},V{1:nr},D{1:nr},DOS{1:nr}] = ...
                deal(jointdata{:});
        catch ME
            reportError(G.oEN.mail_recip, siteID, getReport(ME, 'extended', 'hyperlinks', 'off'), G.tag);
        end
      % QAQC
        RVID = cell2mat(RVID); P = cell2mat(P); T = cell2mat(T); C = cell2mat(C); 
        S = cell2mat(S); V = cell2mat(V); D = cell2mat(D); DOS = cell2mat(DOS);
        if G.doDO
          % Grab the extant DOs...
            DO = zeros(size(T));
            if any(PF)
                extantDOs = queries(conn, 'DO', {RVID(PF)});
                try
                    DO(PF) = [extantDOs{:}];
                catch ME
                    report = getReport(ME, 'extended', 'hyperlinks', 'off');
                    reportError(G.oEN.mail_recip, siteID, [extantDOs{:} report], G.tag);
                end
            end
          % and calculate/populate the missing DOs
            allindices = 1:1:length(T);
            iwoDO = allindices(~PF);
            for j=1:length(iwoDO) % for each Posted Datetime w/out a DO
                curi = iwoDO(j);
              % Get the EquipmentID and CalibrationTypeID whose UTCDeployDatetime 
              % is closest to, but precedes, the current PDT
                indices = (datenum(UTCDDT) < datenum(PDT(curi))); idx = sum(indices);                    
                eid = equipID{idx}; ctyp = calibType{idx};
              % Using the just-acquired eid and ctyp, get the UTCCalibrationBeginDatetime--along with its 
              % coefficients, CalibrationFormulaID, and CalibrationID--most recently preceding that eid's 
              % UTCDeployDatetime
                filter1 = strcmp(ctyp,calibType2) & (eid==[equipID2{:}]);
                cBegin = calibBegin(filter1);
                ctmp = c(filter1,:); cformID = calibForm(filter1); calID = calibID(filter1);
                filter2 = datenum(cBegin) < datenum(UTCDDT{idx});
                idx = sum(filter2);
                coefs = ctmp(idx,:); cformID = cformID{idx}; calID = calID{idx};
              % Calculate DO
                tmp = calcDO(cformID, {P(curi), T(curi), V(curi), DOS(curi)}, coefs(1:6));
                if ischar(tmp)
                    DO(curi) = NaN;
                else
                    DO(curi) = tmp;
                end
              % push DO to CalculatedValue table and toggle ProcessedFlag in RawValue
                ID = num2str(RVID(curi));
                try % As of Oct. 2011, R2011b version of update crashes OTFP, thus the following
                    update(conn, 'CalculatedValue', {'DOCalculated', 'DOCalibrationID'},...
                        {DO(curi), calID} , ['WHERE RawValueID=' ID]);
                catch ME
                    try
                        oldupdate(conn, 'CalculatedValue', {'DOCalculated', 'DOCalibrationID'},...
                            {DO(curi), calID} , ['WHERE RawValueID=' ID]);
                    catch ME
                        data = reportQueryError(G.oEN.mail_recip, siteID, 'pushing DO data',...
                                getReport(ME, 'extended', 'hyperlinks', 'off'), '');
                        return
                    end
                end
                try
                    update(conn, 'RawValue', {'ProcessedFlag'}, {1}, ['WHERE RawValueID=' ID]);
                catch ME
                    try
                        oldupdate(conn, 'RawValue', {'ProcessedFlag'}, {1}, ['WHERE RawValueID=' ID]);
                    catch ME
                        data = reportQueryError(G.oEN.mail_recip, siteID, 'pushing DO data',...
                                getReport(ME, 'extended', 'hyperlinks', 'off'), '');
                        return
                    end
                end
            end
        else
            DO = zeros(size(T)) + NaN;
        end    
        close(conn)
        data = {sitedata, PDTs, P, T, C, S, D, DOS, DO, RVID};
    end
end

function checkResult = check4QueryError(queryResult)
    if isempty(queryResult)
        checkResult = 'Empty cellarray returned';
    elseif ~isempty(strfind(queryResult{1}, 'No Data'))
        checkResult = '''No Data'' returned';
    elseif ~isempty(strfind(queryResult{1}, 'Error'))
        checkResult = [queryResult{:}];
    else
        checkResult = '';
    end
end

function reportError(mail_recip, siteID, report, tag)
    subj = ['Error in rt_data_getter for ' siteID ];
    msg = {report, tag};
%     if ~strcmp(siteID, 'MCH01SR')
%         sendmail(mail_recip, subj, msg)
%     end
end

function result = reportQueryError(mail_recip, siteID, qtype, report, tag)
    subj = ['RT error querying ' siteID ' for ' qtype];
    msg = {report(1:end-3), tag}; % truncation necessary for line feed implied by comma to work
%     if ~strcmp(siteID, 'MCH01SR')
%         sendmail(mail_recip, subj, msg)
%     end
    result = {};
end